package com.tian.framework.security.config;

import com.tian.framework.security.domian.SecurityRole;
import com.tian.framework.security.domian.SecurityUser;
import com.tian.framework.security.server.ISecurityService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.OidcKeycloakAccount;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.representations.AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 自定义实现keycloak用户与系统用户权限的融合
 */
@Configuration
public class OwnAuthenticationProvider implements AuthenticationProvider {
    private static final Logger log = LogManager.getLogger(OwnAuthenticationProvider.class);
    @Autowired
    private ISecurityService iSecurityService;
    private GrantedAuthoritiesMapper grantedAuthoritiesMapper;

    public void setGrantedAuthoritiesMapper(GrantedAuthoritiesMapper grantedAuthoritiesMapper) {
        this.grantedAuthoritiesMapper = grantedAuthoritiesMapper;
    }

    /**
     * 验证Authentication，建立系统使用者信息principal(token)
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws RuntimeException {
        //从token中获取用户信息
        KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
        AccessToken accessToken = getAccessToken((token));
        //获取当前验证用户的keycloak用户库的用户id
        String keycloakId = accessToken.getSubject();
        SecurityUser sysUser = iSecurityService.selectUserByKeycloakId(keycloakId.replace("-", ""));
        if (sysUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        //添加权限
        List<SecurityRole> roles = sysUser.getRoles();
        //添加角色信息
        for (SecurityRole role : roles) {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleKey().toUpperCase()));
        }
        //添加普通权限
        List<String> perms = iSecurityService.selectUserPermissionByUserId(sysUser.getUserId());
        for (String perm : perms) {
            authorities.add(new SimpleGrantedAuthority(perm));
        }
        OidcKeycloakAccount account = token.getAccount();
        OwnKeycloakToken authenticationToken = new OwnKeycloakToken(account, token.isInteractive(), mapAuthorities(authorities));
        authenticationToken.setSecurityUser(sysUser);
        return authenticationToken;
    }
    //获取会话toke
    private AccessToken getAccessToken(KeycloakAuthenticationToken principal) {
        KeycloakAuthenticationToken token = principal;
        KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) token.getPrincipal();
        KeycloakSecurityContext context = keycloakPrincipal.getKeycloakSecurityContext();
        return context.getToken();
    }

    private Collection<? extends GrantedAuthority> mapAuthorities(
            Collection<? extends GrantedAuthority> authorities) {
        return grantedAuthoritiesMapper != null
                ? grantedAuthoritiesMapper.mapAuthorities(authorities)
                : authorities;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return KeycloakAuthenticationToken.class.isAssignableFrom(aClass);
    }
}
